package monitor

import (
	"log"

	"github.com/prometheus/client_golang/prometheus"
)

var (
	_StreamCounter       *prometheus.GaugeVec
	_StreamHeight        *prometheus.GaugeVec
	_StreamWidth         *prometheus.GaugeVec
	_StreamVideoRate     *prometheus.GaugeVec
	_StreamFrameRate     *prometheus.GaugeVec
	_StreamDropFrameRate *prometheus.GaugeVec
	_StreamFrameTotal    *prometheus.GaugeVec
)

func InitStream(namespace, subsystem string) {
	_StreamVideoRate = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_video_rate",
				Help:      "video rate",
			},
			[]string{"host", "device_id"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()

	_StreamFrameRate = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_frame_rate",
				Help:      "frame rate",
			},
			[]string{"host", "device_id"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()

	_StreamDropFrameRate = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_drop_frame_rate",
				Help:      "drop frame rate",
			},
			[]string{"host", "device_id"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()

	_StreamFrameTotal = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_frame_total",
				Help:      "number of frame",
			},
			[]string{"host", "device_id"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()

	_StreamCounter = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_counter",
				Help:      "number of stream",
			},
			[]string{"host"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()

	_StreamWidth = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_width",
				Help:      "width of stream",
			},
			[]string{"host", "device_id"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()

	_StreamHeight = func() *prometheus.GaugeVec {
		vec := prometheus.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: subsystem,
				Name:      "stream_height",
				Help:      "height of stream",
			},
			[]string{"host", "device_id"},
		)
		prometheus.MustRegister(vec)
		return vec
	}()
}

func StreamVideoRate(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamVideoRateSet(host string, deviceId string, rate int32) {
	videoRate := StreamVideoRate(_StreamVideoRate, host, deviceId)
	if videoRate == nil {
		return
	}
	videoRate.Set(float64(rate))
}

func StreamDropFrameRate(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamDropFrameRateSet(host string, deviceId string, rate int32) {
	if host == "" || deviceId == "" || rate < 0 {
		log.Printf("at least one param is emtpy, host: %s, deviceId: %s, rate: %d", host, deviceId, rate)
		return
	}
	videoRate := StreamDropFrameRate(_StreamDropFrameRate, host, deviceId)
	if videoRate == nil {
		return
	}
	videoRate.Set(float64(rate))
}

func StreamFrameRate(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamFrameRateSet(host string, deviceId string, rate int32) {
	if host == "" || deviceId == "" || rate < 0 {
		log.Printf("at least one param is emtpy, host: %s, deviceId: %s, rate: %d", host, deviceId, rate)
		return
	}
	videoRate := StreamFrameRate(_StreamFrameRate, host, deviceId)
	if videoRate == nil {
		return
	}
	videoRate.Set(float64(rate))
}

func StreamFrameTotal(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamFrameTotalSet(host string, deviceId string, recvFrameNum int32) {
	frameTotal := StreamFrameTotal(_StreamFrameTotal, host, deviceId)
	if frameTotal == nil {
		return
	}
	frameTotal.Set(float64(recvFrameNum))
}

func StreamHeight(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamHeightSet(host string, deviceId string, videoHeight int32) {
	streamHeight := StreamHeight(_StreamHeight, host, deviceId)
	if streamHeight == nil {
		return
	}
	streamHeight.Set(float64(videoHeight))
}

func StreamWidth(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamWidthSet(host string, deviceId string, videoWidth int32) {
	streamWidth := StreamWidth(_StreamWidth, host, deviceId)
	if streamWidth == nil {
		return
	}
	streamWidth.Set(float64(videoWidth))
}

func StreamCounter(metricVec *prometheus.GaugeVec, lvs ...string) prometheus.Gauge {
	if metricVec == nil {
		log.Println("_StreamCounter is nil")
		return nil
	}
	return metricVec.WithLabelValues(lvs...)
}

func StreamCounterSet(sessionsNum int, host string) {
	streamCounter := StreamCounter(_StreamCounter, host)
	if streamCounter == nil {
		return
	}
	streamCounter.Set(float64(sessionsNum))
}
